﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using System.IO;
using JSON;
using UnityEditor.Animations;
public class NewAnimatorEditor : EditorWindow {
	#region Member
	const string PathFBX = "Assets/Art/Models/Monstor/FBX";
    const string PathFBXTest = "Assets/Art/Models/Monstor/FBX\\micro_dapengbird_mobile";
	const string PathJSON = "Assets/Script/Module/Base/Editor/JSONAnimatorEditor.txt";

	const string PathAnimatorControl = "Assets/Art/Models/Monstor/Animator/";
	const string PathPrefab = "Assets/Resources/";
	const string PathResources = "Model/";
	#endregion
	#region MenuItem
//	[MenuItem("Assets/Animator/DebugPath")]
//	public static void DebugSelectPath(){
//		Debug.Log (AssetDatabase.GetAssetPath (Selection.activeObject));
//	}
	[MenuItem("Assets/Animator/测试生成Daniao")]
	public static void CreateConstPathTest(){
		CollectFBX (PathFBXTest);
	}
	[MenuItem("Assets/Animator/根据【常量路径】创建【所有】怪物Animator")]
	public static void CreateConstPath(){
		CollectAllFBX (PathFBX);
	}
	[MenuItem("Assets/Animator/根据【当前选中】创建【所有】怪物Animator")]
	public static void Create(){
		Object obj;
		obj = Selection.activeObject;
		if(obj!=null){
			CollectAllFBX (AssetDatabase.GetAssetPath (obj));
		}
	}
	[MenuItem("Assets/Animator/根据【当前选中】创建【单个】怪物Animator")]
	public static void CreateOnlySelect(){
		Object obj;
		obj = Selection.activeObject;
		if(obj!=null){
			CollectFBX (AssetDatabase.GetAssetPath (obj));
		}
	}
	static void CollectAllFBX(string path){
		string[] objs;
		objs = Directory.GetDirectories(path);
		for (int i = 0; i < objs.Length; i++) {
			CollectFBX (objs[i]);
		}
	}

	#endregion
	#region Control
	/// <summary>
	/// 一个FBX的文件夹
	/// </summary>
	/// <param name="path">Path.</param>
	static void CollectFBX(string path){
		string name = Path.GetFileNameWithoutExtension (path);
		AnimatorController cc = CreateAnimatorAC (name);
		GameObject Obj = GetPrefab (name,cc);
		if (Obj == null)
			return;
		CreatePrefab (name,Obj);
		AssetDatabase.Refresh ();
	}
	#endregion
	#region Tool
	static GameObject GetPrefab(string name,AnimatorController cc){
		string path;
		path = PathResources + name;
		//添加到预制
		GameObject obj = Resources.Load<GameObject>(path);
		if (obj == null)
			Debug.Log ("no");
		GameObject parent = null;
		if (obj == null) {
			path = PathFBX + "/" + name + "/" + name;

			obj = AssetDatabase.LoadAssetAtPath<GameObject> (PathFBX+"/"+name+"/"+name+".FBX");
			if (obj == null) {
				Debug.LogError ("找不到FBX:" + name);
				return null;
			}
			obj = GameObject.Instantiate (obj);
			obj.name = name;
			parent = new GameObject (obj.name);
			parent.AddComponent<CharacterController> ();
			obj.transform.parent = parent.transform;
			GameObject firepos = new GameObject ("FirePos");
			firepos.transform.parent = parent.transform;
		}
		Animator animator = obj.GetComponentInChildren<Animator> (true);
		if(animator != null)
			animator.runtimeAnimatorController = cc;
		return parent;
	}
	static AnimatorController CreateAnimatorAC(string name){
		Dictionary<string,AnimatorState> states;
		AnimatorController animatorController = UnityEditor.Animations.AnimatorController.CreateAnimatorControllerAtPath(PathAnimatorControl+name+".controller");
		JSONNode json =  JsonRead.Parse(AssetDatabase.LoadAssetAtPath<TextAsset> (PathJSON).text);
		AddParameter (ref animatorController, json ["Parameter"]);
		states = AddState (name,ref animatorController, json ["State"]);
		AddTranstion (ref animatorController,states, json ["Transtion"]);
		return animatorController;
	}
	static void AddTranstion(ref AnimatorController cc,Dictionary<string,AnimatorState> states,JSONNode node){
		for (int i = 0; i < node.Count; i++) {
			string s1 = node [i] [0].ToString ();
			string s2 = node [i] [1].ToString ();
			string s3 = node [i] [2].ToString ();
			AnimatorConditionMode mode = AnimatorConditionMode.If;
			float targetvalue = 0;
			if (node [i].Count > 4) {
				switch (node [i] [3].ToString ()) {
				case "Equals":
					mode = AnimatorConditionMode.Equals;
					break;
				case "Greater":
					mode = AnimatorConditionMode.Greater;
					break;
				case "If":
					mode = AnimatorConditionMode.If;
					break;
				case "IfNot":
					mode = AnimatorConditionMode.IfNot;
					break;
				case "Less":
					mode = AnimatorConditionMode.Less;
					break;
				case "NotEqual":
					mode = AnimatorConditionMode.NotEqual;
					break;
				}
				targetvalue = node [i] [4].AsFloat;
			}
			AnimatorStateMachine sm = cc.layers [0].stateMachine;
			AnimatorStateTransition tr;
			if (s1 == "anystate" && states.ContainsKey(s2) && s3 != "bytime") {
				tr = sm.AddAnyStateTransition (states [s2]);
				tr.AddCondition (mode, targetvalue, s3);
			}
			else if(states.ContainsKey(s1) && states.ContainsKey(s2)){
				tr = states [s1].AddTransition (states [s2]);
				if (s3 == "bytime") {
					tr.hasExitTime = true;
				} else {
					tr.AddCondition (mode, targetvalue, s3);
				}

			}
		}
	}
	static Dictionary<string,AnimatorState> AddState(string name,ref AnimatorController ac,JSONNode node){
		Dictionary<string,AnimatorState> states = new Dictionary<string, AnimatorState> ();
		AnimatorStateMachine sm = ac.layers [0].stateMachine;
		for (int i = 0; i < node.Count; i++) {
			string statename = node [i][0].ToString ();
			string anifbxname = name + "@" + statename;
			string path = PathFBX + "/" + name + "/" + anifbxname+".FBX";

			Object[] newclip = AssetDatabase.LoadAllAssetsAtPath(path);
			for (int x = 0;x < newclip.Length; x++) {
				AnimationClip clip = newclip [x] as AnimationClip;
				if (clip != null) {
					if (clip.name.Contains (statename)) {
						AnimatorState state = sm.AddState(statename);
						SerializedObject serializedClip = new SerializedObject(clip);
                        AnimationClipSettings_Tools clipSettings = new AnimationClipSettings_Tools(serializedClip.FindProperty("m_AnimationClipSettings"));  
						bool isloop = node [i] [1].AsInt == 1;
						clipSettings.loopTime = isloop;  
						clipSettings.loopBlend = isloop;  
						serializedClip.ApplyModifiedProperties();  
						Motion mo = clip as Motion;
						state.motion = mo;
						states.Add (statename, state);
					}
				}
			}

		}
		return states;
	}
	static void AddParameter(ref AnimatorController ac,JSONNode node){
		for (int i = 0; i < node.Count; i++) {
			switch (node [i][1].ToString()) {
			case "Float":
				ac.AddParameter (node [i][0].ToString (), AnimatorControllerParameterType.Float);	
				break;
			case "Int":
				ac.AddParameter (node [i][0].ToString (), AnimatorControllerParameterType.Int);	
				break;
			case "Bool":
				ac.AddParameter (node [i][0].ToString (), AnimatorControllerParameterType.Bool);	
				break;
			case "Trigger":
				ac.AddParameter (node [i][0].ToString (), AnimatorControllerParameterType.Trigger);	
				break;
			}
		}
	}
	static void CreatePrefab(string name,GameObject obj){
		if (obj == null)
			return;
		PrefabUtility.CreatePrefab (PathPrefab+PathResources+ name+".prefab", obj, ReplacePrefabOptions.ConnectToPrefab);
		GameObject.DestroyImmediate (obj);
	}
	#endregion
}
class AnimationClipSettings_Tools  
{  
	SerializedProperty m_Property;  

	private SerializedProperty Get (string property) { return m_Property.FindPropertyRelative(property); }

    public AnimationClipSettings_Tools(SerializedProperty prop) { m_Property = prop; }  

	public float startTime   { get { return Get("m_StartTime").floatValue; } set { Get("m_StartTime").floatValue = value; } }  
	public float stopTime   { get { return Get("m_StopTime").floatValue; }  set { Get("m_StopTime").floatValue = value; } }  
	public float orientationOffsetY { get { return Get("m_OrientationOffsetY").floatValue; } set { Get("m_OrientationOffsetY").floatValue = value; } }  
	public float level { get { return Get("m_Level").floatValue; } set { Get("m_Level").floatValue = value; } }  
	public float cycleOffset { get { return Get("m_CycleOffset").floatValue; } set { Get("m_CycleOffset").floatValue = value; } }  

	public bool loopTime { get { return Get("m_LoopTime").boolValue; } set { Get("m_LoopTime").boolValue = value; } }  
	public bool loopBlend { get { return Get("m_LoopBlend").boolValue; } set { Get("m_LoopBlend").boolValue = value; } }  
	public bool loopBlendOrientation { get { return Get("m_LoopBlendOrientation").boolValue; } set { Get("m_LoopBlendOrientation").boolValue = value; } }  
	public bool loopBlendPositionY { get { return Get("m_LoopBlendPositionY").boolValue; } set { Get("m_LoopBlendPositionY").boolValue = value; } }  
	public bool loopBlendPositionXZ { get { return Get("m_LoopBlendPositionXZ").boolValue; } set { Get("m_LoopBlendPositionXZ").boolValue = value; } }  
	public bool keepOriginalOrientation { get { return Get("m_KeepOriginalOrientation").boolValue; } set { Get("m_KeepOriginalOrientation").boolValue = value; } }  
	public bool keepOriginalPositionY { get { return Get("m_KeepOriginalPositionY").boolValue; } set { Get("m_KeepOriginalPositionY").boolValue = value; } }  
	public bool keepOriginalPositionXZ { get { return Get("m_KeepOriginalPositionXZ").boolValue; } set { Get("m_KeepOriginalPositionXZ").boolValue = value; } }  
	public bool heightFromFeet { get { return Get("m_HeightFromFeet").boolValue; } set { Get("m_HeightFromFeet").boolValue = value; } }  
	public bool mirror { get { return Get("m_Mirror").boolValue; } set { Get("m_Mirror").boolValue = value; } }  
}  